import datetime
import json
from pkgutil import get_data

import pandas as pd
import requests

import CountUtil
from KlinePanel import KlinePanel
from Repo import Repo
from Strategy import Strategy


class BackTestingRunner:
    def __init__(self, code, count, end):
        """
        :param code: 标的
        :param count: 获取k线数量
        :param end: 结束时间
        """
        self.code = code
        self.count = count
        self.end = end
        self.data = None
        # ma 指标
        self.MA5 = None
        self.MA10 = None
        self.MA20 = None
        # atr 指标
        self.ATR = None
        self.ATRLOW = None
        self.klinePanel = KlinePanel(self, f'out/{code}_kline.html', code)

    def start(self, stategy, initCash):
        # 获取股票代码
        df = self.getdata()
        self.data = df
        close = df.close.values;
        open = df.open.values  # 基础数据定义，只要传入的是序列都可以  Close=df.close.values
        high = df.high.values;
        low = df.low.values  # 例如  CLOSE=list(df.close) 都是一样
        self.MA5 = CountUtil.MA(close, 5)
        self.MA10 = CountUtil.MA(close, 10)
        self.MA20 = CountUtil.MA(close, 20)
        self.ATR = CountUtil.ATR(close, high, low)
        self.ATRLOW = CountUtil.ATRLow(close, high, low)
        repo = Repo(self, initCash)
        stategy.onAttach(repo)
        incomes = []
        # 迭代数据
        for index, row in self.data.iterrows():
            # 执行策略
            stategy.onKlineStep(index, self)
            # 需要各种指标
            incomes.append(repo.getTotalProfitRate(index))
        self.klinePanel.setIncomes(incomes)
        self.klinePanel.draw()

    def getNewPrice(self, index):
        return self.data.close.values[index]
    def getMa20(self, index):
        return self.MA20[index]

    def getAtrLow(self, index):
        return self.ATRLOW[index]
    def mark(self, p):
        self.klinePanel.addMark(p)

    def getdata(self):
        frequency = '240m'
        frequency = frequency.replace('1d', '240m') \
            .replace('1w', '1200m').replace('1M', '7200m');
        mcount = self.count
        ts = int(frequency[:-1]) \
            if frequency[:-1].isdigit() else 1  # 解析K线周期数
        if (self.end != '') & (frequency in ['240m', '1200m', '7200m']):
            end_date = pd.to_datetime(self.end) \
                if not isinstance(self.end, datetime.date) \
                else self.end  # 转换成datetime
            unit = 4 if frequency == '1200m' else 29 if frequency == '7200m' else 1  # 4,29多几个数据不影响速度
            mcount = self.count + (datetime.datetime.now() - end_date).days // unit  # 结束时间到今天有多少天自然日(肯定 >交易日)
            # print(code,end_date,count)
        URL = f'http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol={self.code}&scale={ts}&ma=5&datalen={mcount}'
        print(URL)
        dstr = json.loads(requests.get(URL).content);
        # df=pd.DataFrame(dstr,columns=['day','open','high','low','close','volume'],dtype='float')
        df = pd.DataFrame(dstr, columns=['day', 'open', 'high', 'low', 'close', 'volume'])
        df['open'] = df['open'].astype(float);
        df['high'] = df['high'].astype(float);  # 转换数据类型
        df['low'] = df['low'].astype(float);
        df['close'] = df['close'].astype(float);
        df['volume'] = df['volume'].astype(float)
        return df



